package com.du.config;

import com.du.bean.Color;
import com.du.bean.ColorFactoryBean;
import com.du.bean.Person;
import com.du.bean.Red;
import com.du.condition.LinuxCondition;
import com.du.condition.MyImportBeanDefinitionRegistrar;
import com.du.condition.MyImportSelector;
import com.du.condition.WindowsCondition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;

/**
 * @author djg
 * @date 2020/11/17
 * @des
 */
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})  //导入组件，id默认是组件的全类名
public class MainConfig2 {

    /**
     * 默认是单例的
     * @return
     */

     /**
      * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype
	  * @see ConfigurableBeanFactory#SCOPE_SINGLETON singleton
	  * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
	  * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
      *
      * prototype: 多例，IOC容器启动并不去调用方法创建对象放在容器中，而是每次获取的时候才会调用方法创建对象
      * singleton: 单例（默认），容器启动会调用方法创建bean放到IOC容器中，以后每次直接从容器（map.get()）中拿
      * request: 同一个请求创建一个实例
      * session: 同一个session创建一个实例
      *
      * 懒加载：
      *     单实例bean：默认在容器启动的时候创建对象
      *     懒加载：容器启动不创建对象，第一次使用（获取）Bean创建对象，并初始化。
      *
      */
//    @Scope("prototype") //调整作用域
    @Lazy //懒加载
    @Bean
    public Person person() {
        System.out.println("给容器中添加person");
        return new Person("张三", 25);
    }

    /**
     * @Conditional({Condition})：按照一定的条件进行判断，满足条件给容器中注册bean
     * 可以标注在类和方法上，当标注在类上面的时候，表示满足这个条件，这个类中配置的所有bean注册才能生效
     *
     * 要求：
     *      如果系统是windows，给容器中注册bill
     *      如果系统是linux，给容器中注册linus
     */
    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person02() {
        return new Person("linus", 48);
    }


    /**
     * 给容器中注册组件：
     * 1、包扫描+组件标注注解（@Controller/@service/@Repository/@Component），自己写的类
     * 2、@Bean，导入的第三方包里面的组件
     * 3、@Import，快速给容器中导入一个组件
     *      3.1 @Import(要导入到容器中的组件)，容器中就会自动注册这个组件，id默认是全类名
     *      3.2 ImportSelector，返回需要导入的组件的全类名数组
     *      3.3 ImportBeanDefinitionRegistrar，手动注册Bean到容器中
     * 4、使用Spring提供的FactoryBean（工厂Bean）
     *      4.1 默认获取到的是工厂Bean调用getObject创建的对象
     *      4.2 要获取工厂Bean本身，我们需要给id前面加上一个&，在BeanFactory接口中定义工厂Bean的前缀为&
     */

    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}



















